all repos — caroster @ 6e98fcd2e34e9ae2a75754bd21b2da2c2160b475

[Octree] Group carpool to your event https://caroster.io

frontend/pages/e/[uuid].tsx (view raw)

  1import {useState, useReducer, useEffect} from 'react';
  2import Box from '@material-ui/core/Box';
  3import {makeStyles} from '@material-ui/core/styles';
  4import {useTranslation} from 'react-i18next';
  5import {initializeApollo} from '../../lib/apolloClient';
  6import useToastStore from '../../stores/useToastStore';
  7import useEventStore from '../../stores/useEventStore';
  8import Layout from '../../layouts/Default';
  9import AddToMyEventDialog from '../../containers/AddToMyEventDialog';
 10import TravelColumns from '../../containers/TravelColumns';
 11import NewTravelDialog from '../../containers/NewTravelDialog';
 12import VehicleChoiceDialog from '../../containers/VehicleChoiceDialog';
 13import WelcomeDialog from '../../containers/WelcomeDialog';
 14import EventBar from '../../containers/EventBar';
 15import Loading from '../../containers/Loading';
 16import OnBoardingTour from '../../containers/OnBoardingTour';
 17import {
 18  useUpdateEventMutation,
 19  Event as EventType,
 20  useEventByUuidQuery,
 21  EventByUuidDocument,
 22  EditEventInput,
 23} from '../../generated/graphql';
 24import ErrorPage from '../_error';
 25import AddTravel from '../../containers/TravelColumns/AddTravel';
 26import useProfile from '../../hooks/useProfile';
 27
 28const POLL_INTERVAL = 10000;
 29
 30interface Props {
 31  event: EventType;
 32  eventUUID: string;
 33}
 34
 35const EventPage = props => {
 36  const {t} = useTranslation();
 37  const {event} = props;
 38  if (!event) return <ErrorPage statusCode={404} title={t`event.not_found`} />;
 39  return <Event {...props} />;
 40};
 41
 42const Event = (props: Props) => {
 43  const {eventUUID} = props;
 44  const classes = useStyles();
 45  const {t} = useTranslation();
 46  const {user} = useProfile();
 47  const addToast = useToastStore(s => s.addToast);
 48  const setEvent = useEventStore(s => s.setEvent);
 49  const eventUpdate = useEventStore(s => s.event);
 50  const setIsEditing = useEventStore(s => s.setIsEditing);
 51  const [updateEvent] = useUpdateEventMutation();
 52  const [isAddToMyEvent, setIsAddToMyEvent] = useState(false);
 53  const [openNewTravel, toggleNewTravel] = useReducer(i => !i, false);
 54  const [openVehicleChoice, toggleVehicleChoice] = useReducer(i => !i, false);
 55  const {data: {eventByUUID: event} = {}} = useEventByUuidQuery({
 56    pollInterval: POLL_INTERVAL,
 57    variables: {uuid: eventUUID},
 58  });
 59
 60  useEffect(() => {
 61    if (event) setEvent(event as EventType);
 62  }, [event]);
 63
 64  const onSave = async e => {
 65    try {
 66      const {uuid, ...data} = eventUpdate;
 67      const {id, __typename, travels, users, waitingList, ...input} = data;
 68      await updateEvent({
 69        variables: {uuid, eventUpdate: input as EditEventInput},
 70        refetchQueries: ['eventByUUID'],
 71      });
 72      setIsEditing(false);
 73    } catch (error) {
 74      console.error(error);
 75      addToast(t('event.errors.cant_update'));
 76    }
 77  };
 78
 79  const onShare = async () => {
 80    if (!event) return null;
 81    // If navigator share capability
 82    if (!!navigator.share)
 83      return await navigator.share({
 84        title: `Caroster ${event.name}`,
 85        url: `${window.location.href}`,
 86      });
 87    // Else copy URL in clipboard
 88    else if (!!navigator.clipboard) {
 89      await navigator.clipboard.writeText(window.location.href);
 90      addToast(t('event.actions.copied'));
 91      return true;
 92    }
 93  };
 94
 95  if (!event) return <Loading />;
 96
 97  return (
 98    <Layout
 99      pageTitle={t('event.title', {title: event.name})}
100      menuTitle={t('event.title', {title: event.name})}
101      displayMenu={false}
102    >
103      <EventBar
104        event={event}
105        onAdd={setIsAddToMyEvent}
106        onSave={onSave}
107        onShare={onShare}
108      />
109      <TravelColumns toggle={toggleVehicleChoice} />
110      <Box className={classes.bottomRight}>
111        <AddTravel toggle={user ? toggleVehicleChoice : toggleNewTravel} />
112      </Box>
113      <NewTravelDialog open={openNewTravel} toggle={toggleNewTravel} />
114      <VehicleChoiceDialog
115        open={openVehicleChoice}
116        toggle={toggleVehicleChoice}
117        toggleNewTravel={toggleNewTravel}
118      />
119      <AddToMyEventDialog
120        event={event}
121        open={isAddToMyEvent}
122        onClose={() => setIsAddToMyEvent(false)}
123      />
124      <WelcomeDialog />
125      <OnBoardingTour />
126    </Layout>
127  );
128};
129
130export async function getServerSideProps(ctx) {
131  const {uuid} = ctx.query;
132  const apolloClient = initializeApollo();
133  const {data = {}} = await apolloClient.query({
134    query: EventByUuidDocument,
135    variables: {uuid},
136  });
137  const {eventByUUID: event} = data;
138  const {host = ''} = ctx.req.headers;
139
140  return {
141    props: {
142      event,
143      eventUUID: uuid,
144      metas: {
145        title: event?.name || '',
146        url: `https://${host}${ctx.resolvedUrl}`,
147      },
148    },
149  };
150}
151
152const useStyles = makeStyles(theme => ({
153  bottomRight: {
154    position: 'absolute',
155    bottom: theme.spacing(1),
156    right: theme.spacing(6),
157    width: 200,
158  },
159}));
160
161export default EventPage;